package scala.afei.drum;

import afei.drum.R
import android.animation.Animator
import android.animation.AnimatorListenerAdapter
import android.animation.ObjectAnimator
import android.animation.ValueAnimator
import android.app.Activity
import android.content.Context
import android.content.Intent
import android.graphics.drawable.shapes.OvalShape
import android.graphics.drawable.ShapeDrawable
import android.graphics.Canvas
import android.graphics.Paint
import android.graphics.Point
import android.graphics.Rect
import android.media.AudioManager
import android.media.SoundPool
import android.os.Bundle
import android.os.Environment
import android.os.Handler
import android.os.Message
import android.view.ViewGroup.LayoutParams
import android.view.animation.AccelerateInterpolator
import android.view.MotionEvent
import android.view.View
import android.view.Window
import android.view.WindowManager
import android.widget.LinearLayout

object DrumPlayActivity {
  val DRUM_KEY_MDOE: String = "drum_mode";
  val DRUM_KEY_PUZI: String = "drum_puzi";
  val DRUM_KEY_MUSIC: String = "drum_music";

  val DRUM_MODE_FREE = "free";
  val DRUM_MODE_MUSIC = "music";

  // 东西掉落时间是2s
  val DRUM_MOVE_TIME = 1000;

  // mHandler 的what
  val WHAT_CREATE_BALL = 100;

  // 距离每一个btn目的地与底部的偏移
  val END_Y_OFFSET = 50;
  
  // 每秒多少帧
  val FRAME_PER_SECOND = 15;
  
  // 每帧多少秒。
  val TIME_PER_FRAME = 1000 / 15;
  
    /** Drops the 'i'th element of a list. 
   */ 
  def dropIndex[T](xs: List[T], n: Int) : List[T]= { 
    val (l1, l2) = xs splitAt n 
    l1 ::: (l2 drop 1) 
  } 

}

/**
 * 两种模式
 * 1.自由打
 * 2.有谱子，这时可以选择是否播放谱子
 * @author zhangpengfei
 *
 */
class DrumPlayActivity extends Activity {

  var mCurMode: String = null;

  var mPuzi: String = null;
  var mMsuic: String = null;

  val DELAY_TIME = 200; // 200ms
  
  var mSoundPool : SoundPool = null;

  private var mCrash, mTom_2, mTom_3, mRide, mHiHat, mSnare, mKick, mTom_1: View = null;

//  private var mCrashPlayer, mTom_2Player, mTom_3Player, mRidePlayer, mHiHatPlayer, mSnarePlayer, mKickPlayer, mTom_1Player: MediaPlayer = null;

  private var mAllSound = new Array[Int](8);

  var MAX_WIDTH = 0;
  var MAX_HEIGHT = 0;

  var mHandler: Handler = null;

  var mMainView: MainView = null;

  override def onCreate(savedInstanceState: Bundle) = {
    super.onCreate(savedInstanceState);

    // 全屏
    requestWindowFeature(Window.FEATURE_NO_TITLE); //隐藏标题
    getWindow().setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN,
      WindowManager.LayoutParams.FLAG_FULLSCREEN); //设置全屏

    MAX_WIDTH = getWindow().getWindowManager().getDefaultDisplay().getWidth();
    MAX_HEIGHT = getWindow().getWindowManager().getDefaultDisplay().getHeight();
    println("width = " + MAX_WIDTH + " height = " + MAX_HEIGHT);

    val root = new LinearLayout(this);
    root.setLayoutParams(new LayoutParams(LayoutParams.FILL_PARENT, LayoutParams.FILL_PARENT));
    mMainView = new MainView(this);
    root.addView(mMainView);
    setContentView(root);

    processIntent(getIntent(), true);
    createPlayers();

    mHandler = new Handler() {
      override def handleMessage(msg: Message) = {
        println("handler rcv msg " + msg.what + " arg1 = " + msg.arg1 + " arg2 = " + msg.arg2);
        msg.what match {
          case DrumPlayActivity.WHAT_CREATE_BALL => mMainView.createMoveBalls(msg.arg1);
        }
      }
    };

    new Thread(mMainView).start();
    new Puzi(this, mHandler, Environment.getExternalStorageDirectory() + "/demo_beat").start();
  }

  class MainView(context: Context) extends View(context) with Runnable {
    //, attrs : AttributeSet , defStyle : Int
    var mRect: Array[Rect] = new Array[Rect](8);
    var balls: List[ShapeHolder] = Nil;
    var isRunning = false;
    
    initRect();
    
    def run() = {
      work();
    }

    def work() = {
      isRunning = true;
      var startTime, endTime : Long = 0;
      startTime = System.currentTimeMillis();
      endTime = startTime;
      while (isRunning) {
    	  startTime = endTime;
    	  logic();
    	  endTime = System.currentTimeMillis();
    	  if (endTime - startTime < DrumPlayActivity.TIME_PER_FRAME) {
    	    Thread.sleep(endTime - startTime);
    	  }
    	  postInvalidate();
      }
    }
    
    def logic() = {
      var t : Long = System.currentTimeMillis();
      
      balls = balls.filter((ba : ShapeHolder) => System.currentTimeMillis() - ba.startTime < ba.duration);
      for (shape <- balls) {
        	shape.logic();
      }
    }
    
    def initRect() = {
      for (i <- 0 until 4) {
        for (j <- 0 until 2) {
          mRect(j * 4 + i) = new Rect(MAX_WIDTH / 4 * i, MAX_HEIGHT / 2 * j, MAX_WIDTH / 4 * (i + 1),
            MAX_HEIGHT / 2 * (j + 1));
        }
      }
    }

    def createMoveBalls(drumInfo: Int) = {
      // 最高位，crash，tom1，tom2，tom3，ride，kick，snare，hihat
      // 鼓在rect中的顺序 crash, tom2, tom3, ride, hihat, snare, kick, tom1
      if ((drumInfo & 128) > 0) {
        createMoveBallFromRect(0);
      } 
      if ((drumInfo & 64) > 0) {
        createMoveBallFromRect(7)
      }
      if ((drumInfo & 32) > 0) {
        createMoveBallFromRect(1)
      }
      if ((drumInfo & 16) > 0) {
        createMoveBallFromRect(2)
      }
      if ((drumInfo & 8) > 0) {
        createMoveBallFromRect(3)
      }
      if ((drumInfo & 4) > 0) {
        createMoveBallFromRect(6)
      }
      if ((drumInfo & 2) > 0) {
        createMoveBallFromRect(5)
      }
      if ((drumInfo & 1) > 0) {
        createMoveBallFromRect(4)
      }
    }

    def createMoveBallFromRect(index: Int) = {
      println("createMoveBall " + mRect(index).left + " " + mRect(index).top
        + " " + mRect(index).right + " " + mRect(index).bottom);
      createMoveBall(mRect(index).left, mRect(index).top, mRect(index).right, mRect(index).bottom,
        DrumPlayActivity.DRUM_MOVE_TIME);
    }

    def createMoveBall(startX: Int, startY: Int, endX: Int, endY: Int, duration: Int) = {
      var circle: OvalShape = new OvalShape();
      var radius = 25;
      circle.resize(radius * 2, radius * 2);
      var shapeHolder: ShapeHolder = new ShapeHolder(circle);
      
      shapeHolder.startX = startX - radius;
      shapeHolder.startY = startY - radius;
      shapeHolder.endX = endX - radius;
      shapeHolder.endY = endY - radius;
      shapeHolder.startTime = System.currentTimeMillis();
      shapeHolder.duration = duration;
      
      var red: Int = (Math.random * 255).toInt;
      var green = (Math.random * 255).toInt;
      var blue = (Math.random * 255).toInt;
      var color = 0xff000000 | red << 16 | green << 8 | blue;
      var paint = new Paint(); 
      paint.setColor(color);
      shapeHolder.setPaint(paint);
      balls = shapeHolder :: balls;

//      var bounceAnim: ValueAnimator = ObjectAnimator.ofFloat(shapeHolder, "y", startY, endY);
//      bounceAnim.setDuration(duration);
//      bounceAnim.setInterpolator(new AccelerateInterpolator());
//      bounceAnim.start();
//
//      bounceAnim.addListener(new AnimatorListenerAdapter() {
//        override def onAnimationEnd(animation: Animator) {
////          balls.remove((animation.asInstanceOf[ObjectAnimator]).getTarget());
//        }
//      });
    }

    override def onDraw(canvas: Canvas) = {
      drawBack(canvas);
      drawBalls(canvas);
    }

    private def drawBalls(canvas: Canvas) = {
      println("ball.size = " + balls.length)
      for (shapeHolder <- balls) {
    	  shapeHolder.draw(canvas);
      }
    }

    private def drawBack(canvas: Canvas) = {
      var paint: Paint = new Paint();
      //            paint.setARGB(255, 128, 128, 128);
      var color: Int = 0xff000000;
      for (i <- 0 until mRect.length) {
        color += 0x0f1f11;
        paint.setColor(color);
        canvas.drawRect(mRect(i), paint);

        color += 0x0000aa;
        paint.setColor(color);
        canvas.drawLine(mRect(i).left, mRect(i).bottom - DrumPlayActivity.END_Y_OFFSET, mRect(i).right,
          mRect(i).bottom - DrumPlayActivity.END_Y_OFFSET, paint);
      }
    }

    override def onTouchEvent(event: MotionEvent): Boolean = {
      var action = event.getActionMasked();
      if (action == MotionEvent.ACTION_DOWN || action == MotionEvent.ACTION_POINTER_DOWN) {
        var i = event.getActionIndex();
        var p: Point = new Point(event.getX(i).toInt, event.getY(i).toInt);
        for (j <- 0 until mRect.length) {
          if (mRect(j).contains(p.x, p.y)) {
            click(j);
          }
        }
        println(event.getX(0) + " " + event.getY(0));
      }
      return true;
    }


    def click(index: Int) = {
      mSoundPool.play(mAllSound(index), 1, 1, 1, 0, 1);
      
//      var mp: MediaPlayer = mAllSound(index);
//      if (mp.isPlaying()) {
//        mp.seekTo(0);
//      }
//      mp.start();
    }
  }

  def createPlayers() = {
    mSoundPool = new SoundPool(8, AudioManager.STREAM_MUSIC, 0);
    mAllSound(0) = mSoundPool.load(this, R.raw.crash, 1);
    mAllSound(1) = mSoundPool.load(this, R.raw.tom2, 1);
    mAllSound(2) = mSoundPool.load(this, R.raw.tom3, 1);
    mAllSound(3) = mSoundPool.load(this, R.raw.ride, 1);
    mAllSound(4) = mSoundPool.load(this, R.raw.hihat, 1);
    mAllSound(5) = mSoundPool.load(this, R.raw.snare, 1);
    mAllSound(6) = mSoundPool.load(this, R.raw.kick, 1);
    mAllSound(7) = mSoundPool.load(this, R.raw.tom1, 1);
  }


  def processIntent(intent: Intent, isCreate: Boolean) = {
    mCurMode = intent.getStringExtra(DrumPlayActivity.DRUM_KEY_MDOE);
    if (DrumPlayActivity.DRUM_MODE_MUSIC.equals(mCurMode)) {
      mPuzi = intent.getStringExtra(DrumPlayActivity.DRUM_KEY_PUZI);
      mMsuic = intent.getStringExtra(DrumPlayActivity.DRUM_MODE_MUSIC);
    }

  }

}
